#!/usr/bin/env bash
set -Eeuo pipefail

# ============================================================
# SatNOGS Auto Scheduler instance wrapper
#
# Usage:
#   ./bin/run-instance <instance>
#
# Example:
#   ./bin/run-instance uhf
#   ./bin/run-instance uhf-2
#   ./bin/run-instance vhf
# ============================================================

ROOT="/path/to/satnogs-auto-scheduler"
CONFIG_DIR="${ROOT}/config"
ENV_FILE="${ROOT}/.env"
SCHEDULER="${ROOT}/.venv/bin/schedule_single_station"

# ------------------------------------------------------------
# Argument check
# ------------------------------------------------------------

if [[ $# -ne 1 ]]; then
    echo "Usage: $0 <instance>" >&2
    exit 2
fi

INSTANCE="$1"

# Avoid accidental path traversal etc.
if [[ ! "$INSTANCE" =~ ^[A-Za-z0-9._-]+$ ]]; then
    echo "Invalid instance name: $INSTANCE" >&2
    exit 2
fi

CONFIG_FILE="${CONFIG_DIR}/${INSTANCE}.conf"

if [[ ! -r "$CONFIG_FILE" ]]; then
    echo "Configuration file not found or not readable:" >&2
    echo "  $CONFIG_FILE" >&2
    exit 1
fi

if [[ ! -x "$SCHEDULER" ]]; then
    echo "schedule_single_station not found:" >&2
    echo "  $SCHEDULER" >&2
    exit 1
fi

# ------------------------------------------------------------
# Load environment
# ------------------------------------------------------------

# Export variables so CACHE_DIR, CACHE_AGE, API tokens, etc.
# are inherited by schedule_single_station.
set -a

if [[ -r "$ENV_FILE" ]]; then
    # shellcheck disable=SC1090
    source "$ENV_FILE"
fi

# shellcheck disable=SC1090
source "$CONFIG_FILE"

set +a

# ------------------------------------------------------------
# Helpers
# ------------------------------------------------------------

is_true() {
    case "${1:-0}" in
        1|true|TRUE|yes|YES|on|ON)
            return 0
            ;;
        0|false|FALSE|no|NO|off|OFF|"")
            return 1
            ;;
        *)
            echo "Invalid boolean value: $1" >&2
            exit 2
            ;;
    esac
}

# ------------------------------------------------------------
# Required settings
# ------------------------------------------------------------

if [[ -z "${STATION_ID:-}" ]]; then
    echo "STATION_ID is not set in ${CONFIG_FILE}" >&2
    exit 1
fi

# ------------------------------------------------------------
# Build command line
# ------------------------------------------------------------

ARGS=(
    -s "$STATION_ID"
)

# ----- Scheduling interval -----

if [[ -n "${STARTTIME:-}" ]]; then
    ARGS+=(-t "$STARTTIME")
fi

if [[ -n "${DURATION:-}" ]]; then
    ARGS+=(-d "$DURATION")
fi

if [[ -n "${MAX_OBSERVATION_DURATION:-}" ]]; then
    ARGS+=(-o "$MAX_OBSERVATION_DURATION")
fi

# ----- Pass constraints -----

if [[ -n "${MIN_CULMINATION:-}" ]]; then
    ARGS+=(-m "$MIN_CULMINATION")
fi

# -z and -r represent alternative ways of defining the horizon.
# If HORIZON=1, -z takes precedence and MIN_RISESET is not passed.
if is_true "${HORIZON:-0}"; then
    ARGS+=(-z)
elif [[ -n "${MIN_RISESET:-}" ]]; then
    ARGS+=(-r "$MIN_RISESET")
fi

# Azimuth window
if [[ -n "${START_AZIMUTH:-}" || -n "${STOP_AZIMUTH:-}" ]]; then
    if [[ -z "${START_AZIMUTH:-}" || -z "${STOP_AZIMUTH:-}" ]]; then
        echo "START_AZIMUTH and STOP_AZIMUTH must be specified together." >&2
        exit 1
    fi

    ARGS+=(
        -b "$START_AZIMUTH"
        -e "$STOP_AZIMUTH"
    )
fi

# Fixed antenna pointing constraint.
#
# Examples in conf:
#   POINTING="30"
#   POINTING="30 180"
#   POINTING="30 270 45"
#
# These must become separate CLI arguments.
if [[ -n "${POINTING:-}" ]]; then
    read -r -a POINTING_ARGS <<< "$POINTING"

    if (( ${#POINTING_ARGS[@]} < 1 || ${#POINTING_ARGS[@]} > 3 )); then
        echo "POINTING must contain 1 to 3 values." >&2
        exit 1
    fi

    ARGS+=(-i "${POINTING_ARGS[@]}")
fi

# ----- Priority handling -----

if [[ -n "${PRIORITY_FILE:-}" ]]; then
    if [[ ! -r "$PRIORITY_FILE" ]]; then
        echo "Priority file not found or not readable:" >&2
        echo "  $PRIORITY_FILE" >&2
        exit 1
    fi

    ARGS+=(-P "$PRIORITY_FILE")
fi

if [[ -n "${MIN_PRIORITY:-}" ]]; then
    ARGS+=(-M "$MIN_PRIORITY")
fi

# Note:
# In schedule_single_station, -f means that only explicitly listed
# priority transmitters are considered.
if is_true "${ONLY_PRIORITY:-0}"; then
    if [[ -z "${PRIORITY_FILE:-}" ]]; then
        echo "ONLY_PRIORITY=1 requires PRIORITY_FILE." >&2
        exit 1
    fi

    ARGS+=(-f)
fi

# ----- Scheduling spacing -----

if [[ -n "${WAIT:-}" ]]; then
    ARGS+=(-w "$WAIT")
fi

# ----- Station state -----

if is_true "${ALLOW_TESTING:-0}"; then
    ARGS+=(-T)
fi

if is_true "${ALLOW_UNAVAILABLE:-0}"; then
    ARGS+=(-U)
fi

# ----- Operation -----

if is_true "${DRY_RUN:-0}"; then
    ARGS+=(-n)
fi

if is_true "${FLUSH_CACHE:-0}"; then
    ARGS+=(--flush-cache)
fi

if [[ -n "${LOG_LEVEL:-}" ]]; then
    ARGS+=(-l "$LOG_LEVEL")
fi

# ----- Local extension: truncate overlapping priority passes -----

if is_true "${TRUNCATE_OVERLAPS:-0}"; then
    ARGS+=(--truncate-overlaps)
fi

# ------------------------------------------------------------
# Optional escape hatch for future CLI arguments
#
# In conf:
#   EXTRA_ARGS=(--some-option value)
#
# Do NOT define EXTRA_ARGS as a plain quoted string.
# ------------------------------------------------------------

if declare -p EXTRA_ARGS >/dev/null 2>&1; then
    if declare -p EXTRA_ARGS 2>/dev/null | grep -q '^declare -a'; then
        ARGS+=("${EXTRA_ARGS[@]}")
    else
        echo "EXTRA_ARGS must be a Bash array, for example:" >&2
        echo '  EXTRA_ARGS=(--foo bar)' >&2
        exit 1
    fi
fi

# ------------------------------------------------------------
# Execute
# ------------------------------------------------------------

echo "Running auto-scheduler instance: ${INSTANCE}"
echo "Station ID: ${STATION_ID}"

exec "$SCHEDULER" "${ARGS[@]}"